<!DOCTYPE html>
<html lang="en">
    <head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="format-detection" content="telephone=no" />

  <title>
    37|案例篇：DNS 解析时快时慢，我该怎么办？ | 迪克猪的博客
  </title>

  
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
  <link rel="manifest" href="/manifest.json" />
  <meta name="theme-color" content="#ffffff" />

  
  <link
    rel="stylesheet"
    href="https://unpkg.com/modern-normalize@0.6.0/modern-normalize.css"
  />

  
  
  
  
  <link rel="stylesheet" href="https://zsy619.github.io/style.min.f7761d111b74dd5c07f0111decee92938c12abc42e0fd319e1a07483e248b54e.css" integrity="sha256-93YdERt03VwH8BEd7O6Sk4wSq8QuD9MZ4aB0g&#43;JItU4=" />

  
  
    
  
</head>

    <body>
        <header id="header">
  <div class="header_container">
    <h1 class="sitetitle">
      <a href="https://zsy619.github.io" title="迪克猪的博客">迪克猪的博客</a>
    </h1>
    <nav class="navbar">
      <ul>
        <li><a href="https://zsy619.github.io">Home</a></li>
        
          <li>
            <a href="/post/">
              
              <span>LINUX性能优化</span>
            </a>
          </li>
        
          <li>
            <a href="/csapp/">
              
              <span>深入理解计算机系统_第三版</span>
            </a>
          </li>
        
          <li>
            <a href="/golang/">
              
              <span>golang</span>
            </a>
          </li>
        
          <li>
            <a href="/docker/">
              
              <span>容器</span>
            </a>
          </li>
        
          <li>
            <a href="/flutter/">
              
              <span>Flutter</span>
            </a>
          </li>
        
          <li>
            <a href="/know/">
              
              <span>知识点</span>
            </a>
          </li>
        
          <li>
            <a href="/categories/">
              
              <span>目录</span>
            </a>
          </li>
        
          <li>
            <a href="/about/">
              
              <span>关于</span>
            </a>
          </li>
        
        <li class="hide-sm"><a href="https://zsy619.github.io/index.xml" type="application/rss+xml">RSS</a></li>
      </ul>
    </nav>
  </div>
</header>

        
<section id="main">
  <article class="post content">
    <h2 class="title">37|案例篇：DNS 解析时快时慢，我该怎么办？</h2>
    <div class="post_content">
      <p>Linux 网络基于 TCP/IP 协议栈构建，而在协议栈的不同层，我们所关注的网络性能也不尽相同。</p>
<p>在应用层，我们关注的是应用程序的并发连接数、每秒请求数、处理延迟、错误数等，可以使用 wrk、JMeter 等工具，模拟用户的负载，得到想要的测试结果。</p>
<p>而在传输层，我们关注的是 TCP、UDP 等传输层协议的工作状况，比如 TCP 连接数、 TCP 重传、TCP 错误数等。此时，你可以使用 iperf、netperf 等，来测试 TCP 或 UDP 的性能。</p>
<p>再向下到网络层，我们关注的则是网络包的处理能力，即 PPS。Linux 内核自带的 pktgen，就可以帮你测试这个指标。</p>
<p>DNS（Domain Name System），即域名系统，是互联网中最基础的一项服务，主要提供域名和 IP 地址之间映射关系的查询服务。</p>
<p>DNS 不仅方便了人们访问不同的互联网服务，更为很多应用提供了，动态服务发现和全局负载均衡（Global Server Load Balance，GSLB）的机制。这样，DNS 就可以选择离用户最近的 IP 来提供服务。即使后端服务的 IP 地址发生变化，用户依然可以用相同域名来访问。</p>
<h3 id="域名与-dns-解析">域名与 DNS 解析</h3>
<p>域名是全球唯一的，需要通过专门的域名注册商才可以申请注册。为了组织全球互联网中的众多计算机，域名同样用点来分开，形成一个分层的结构。而每个被点分割开的字符串，就构成了域名中的一个层级，并且位置越靠后，层级越高。</p>
<p><img src="../../images/20200707-1504-18.png" alt=""></p>
<p>域名主要是为了方便让人记住，而 IP 地址是机器间的通信的真正机制。</p>
<p>把域名转换为 IP 地址的服务，也就是域名解析服务（DNS），而对应的服务器就是域名服务器，网络协议则是 DNS 协议。</p>
<p>DNS 协议在 TCP/IP 栈中属于应用层，不过实际传输还是基于 UDP 或者 TCP 协议（UDP 居多） ，并且域名服务器一般监听在端口 53 上。</p>
<p>DNS 服务通过资源记录的方式，来管理所有数据，它支持 A、CNAME、MX、NS、PTR 等多种类型的记录。比如：</p>
<ul>
<li>A 记录，用来把域名转换成 IP 地址；</li>
<li>CNAME 记录，用来创建别名；</li>
<li>而 NS 记录，则表示该域名对应的域名服务器地址。</li>
</ul>
<p>以极客时间的网站 time.geekbang.org 为例，执行下面的 nslookup 命令，就可以查询到这个域名的 A 记录，可以看到，它的 IP 地址是 39.106.233.176：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ nslookup time.geekbang.org
<span style="color:#75715e"># 域名服务器及端口信息</span>
Server:    114.114.114.114
Address:  114.114.114.114#53

<span style="color:#75715e"># 非权威查询结果</span>
Non-authoritative answer:
Name:  time.geekbang.org
Address: 39.106.233.17
</code></pre></div><p>除了 nslookup，另外一个常用的 DNS 解析工具 dig ，就提供了 trace 功能，可以展示递归查询的整个过程。比如你可以执行下面的命令，得到查询结果：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">
<span style="color:#75715e"># +trace表示开启跟踪查询</span>
<span style="color:#75715e"># +nodnssec表示禁止DNS安全扩展</span>
$ dig +trace +nodnssec time.geekbang.org

; &lt;&lt;&gt;&gt; DiG 9.11.3-1ubuntu1.3-Ubuntu &lt;&lt;&gt;&gt; +trace +nodnssec time.geekbang.org
;; global options: +cmd
.      <span style="color:#ae81ff">322086</span>  IN  NS  m.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  a.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  i.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  d.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  g.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  l.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  c.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  b.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  h.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  e.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  k.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  j.root-servers.net.
.      <span style="color:#ae81ff">322086</span>  IN  NS  f.root-servers.net.
;; Received <span style="color:#ae81ff">239</span> bytes from 114.114.114.114#53<span style="color:#f92672">(</span>114.114.114.114<span style="color:#f92672">)</span> in <span style="color:#ae81ff">1340</span> ms

org.      <span style="color:#ae81ff">172800</span>  IN  NS  a0.org.afilias-nst.info.
org.      <span style="color:#ae81ff">172800</span>  IN  NS  a2.org.afilias-nst.info.
org.      <span style="color:#ae81ff">172800</span>  IN  NS  b0.org.afilias-nst.org.
org.      <span style="color:#ae81ff">172800</span>  IN  NS  b2.org.afilias-nst.org.
org.      <span style="color:#ae81ff">172800</span>  IN  NS  c0.org.afilias-nst.info.
org.      <span style="color:#ae81ff">172800</span>  IN  NS  d0.org.afilias-nst.org.
;; Received <span style="color:#ae81ff">448</span> bytes from 198.97.190.53#53<span style="color:#f92672">(</span>h.root-servers.net<span style="color:#f92672">)</span> in <span style="color:#ae81ff">708</span> ms

geekbang.org.    <span style="color:#ae81ff">86400</span>  IN  NS  dns9.hichina.com.
geekbang.org.    <span style="color:#ae81ff">86400</span>  IN  NS  dns10.hichina.com.
;; Received <span style="color:#ae81ff">96</span> bytes from 199.19.54.1#53<span style="color:#f92672">(</span>b0.org.afilias-nst.org<span style="color:#f92672">)</span> in <span style="color:#ae81ff">1833</span> ms

time.geekbang.org.  <span style="color:#ae81ff">600</span>  IN  A  39.106.233.176
;; Received <span style="color:#ae81ff">62</span> bytes from 140.205.41.16#53<span style="color:#f92672">(</span>dns10.hichina.com<span style="color:#f92672">)</span> in <span style="color:#ae81ff">4</span> ms

</code></pre></div><p>dig trace 的输出，主要包括四部分。</p>
<ul>
<li>第一部分，是从 114.114.114.114 查到的一些根域名服务器（.）的 NS 记录。</li>
<li>第二部分，是从 NS 记录结果中选一个（h.root-servers.net），并查询顶级域名 org. 的 NS 记录。</li>
<li>第三部分，是从 org. 的 NS 记录中选择一个（b0.org.afilias-nst.org），并查询二级域名 geekbang.org. 的 NS 服务器。</li>
<li>最后一部分，就是从 geekbang.org. 的 NS 服务器（dns10.hichina.com）查询最终主机 time.geekbang.org. 的 A 记录。</li>
</ul>
<p><img src="../../images/20200707-1519-46.png" alt=""></p>
<p>不仅仅是发布到互联网的服务需要域名，很多时候，我们也希望能对局域网内部的主机进行域名解析（即内网域名，大多数情况下为主机名）。Linux 也支持这种行为。</p>
<p>可以把主机名和 IP 地址的映射关系，写入本机的 /etc/hosts 文件中。这样，指定的主机名就可以在本地直接找到目标 IP。比如，你可以执行下面的命令来操作：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">
$ cat /etc/hosts
127.0.0.1   localhost localhost.localdomain
::1         localhost6 localhost6.localdomain6
192.168.0.100 domain.com

</code></pre></div><h3 id="案例分析">案例分析</h3>
<h4 id="案例-1dns-解析失败">案例 1：DNS 解析失败</h4>
<h4 id="案例-2dns-解析不稳定">案例 2：DNS 解析不稳定</h4>
<p>dnsmasq 是最常用的 DNS 缓存服务之一，还经常作为 DHCP 服务来使用。它的安装和配置都比较简单，性能也可以满足绝大多数应用程序对 DNS 缓存的需求。</p>
<h3 id="小结">小结</h3>
<p>在应用程序的开发过程中，我们必须考虑到 DNS 解析可能带来的性能问题，掌握常见的优化方法。这里，我总结了几种常见的 DNS 优化方法。</p>
<ul>
<li>对 DNS 解析的结果进行缓存。缓存是最有效的方法，但要注意，一旦缓存过期，还是要去 DNS 服务器重新获取新记录。不过，这对大部分应用程序来说都是可接受的。</li>
<li>对 DNS 解析的结果进行预取。这是浏览器等 Web 应用中最常用的方法，也就是说，不等用户点击页面上的超链接，浏览器就会在后台自动解析域名，并把结果缓存起来。</li>
<li>使用 HTTPDNS 取代常规的 DNS 解析。这是很多移动应用会选择的方法，特别是如今域名劫持普遍存在，使用 HTTP 协议绕过链路中的 DNS 服务器，就可以避免域名劫持的问题。</li>
<li>基于 DNS 的全局负载均衡（GSLB）。这不仅为服务提供了负载均衡和高可用的功能，还可以根据用户的位置，返回距离最近的 IP 地址。</li>
</ul>

    </div>
    <div class="info post_meta">
      <time datetime=2020-07-07T11:25:42&#43;0800 class="date">Tuesday, July 7, 2020</time>
      
        <ul class="tags">
        
          <li> <a href="https://zsy619.github.io/tags/linux%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96">linux性能优化</a> </li>
        
          <li> <a href="https://zsy619.github.io/tags/linux">linux</a> </li>
        
        </ul>
      
      
    </div>
    <div class="clearfix"></div>
  </article>
  
    <div class="other_posts">
      
      <a href="https://zsy619.github.io/post/36%E5%A5%97%E8%B7%AF%E7%AF%87%E6%80%8E%E4%B9%88%E8%AF%84%E4%BC%B0%E7%B3%BB%E7%BB%9F%E7%9A%84%E7%BD%91%E7%BB%9C%E6%80%A7%E8%83%BD/" class="prev">36|套路篇：怎么评估系统的网络性能？</a>
      
      
      <a href="https://zsy619.github.io/post/38%E6%A1%88%E4%BE%8B%E7%AF%87%E6%80%8E%E4%B9%88%E4%BD%BF%E7%94%A8-tcpdump-%E5%92%8C-wireshark-%E5%88%86%E6%9E%90%E7%BD%91%E7%BB%9C%E6%B5%81%E9%87%8F/" class="next">38|案例篇：怎么使用 tcpdump 和 Wireshark 分析网络流量？</a>
      
    </div>
    <aside id="comments">
</aside>

  
</section>

        <a id="back_to_top" title="Go To Top" href="#">
  <span>
    <svg viewBox="0 0 24 24">
      <path fill="none" d="M0 0h24v24H0z"></path>
      <path d="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71z"></path>
    </svg>
  </span>
</a>

        <footer id="footer">
  <p>
    <span>&copy; 2021 <a href="https://zsy619.github.io" title="迪克猪的博客">迪克猪的博客</a> </span>
    <span>Built with <a rel="nofollow" target="_blank" href="https://gohugo.io">Hugo</a></span>
    <span>Theme by <a rel="nofollow" target="_blank" href="https://github.com/wayjam/hugo-theme-mixedpaper">WayJam</a></span>
  </p>

  <script src="https://zsy619.github.io/js/main.min.8b182175f5874aeed0acc0979345c98d4bde22208ec4f36cc1d6e3102acb4b10.js" integrity="sha256-ixghdfWHSu7QrMCXk0XJjUveIiCOxPNswdbjECrLSxA=" crossorigin="anonymous" async></script>
</footer>

    </body>
</html>
